﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Input;
using System.Data;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Threading;
using System.Diagnostics;



namespace PracaInz_v0
{
    class DrawTree
    {
         //vektor wczytuje sie z pliku i podswietla droge przez ktora ten vektor przeszedl
         //przerobic przesylanie danych na eventy (zajecia 18.03)
        /*
         * wczytac wektory z pliku przepuscic przez drzewo zeby wiedziec gdzie ktory wpadl (Split Attr Number --> x na ktory jest podzial)
         * (Split Attr Value --> wartosc na ktorej odbywa sie podzial)     jest
         * zapisac ktore wektory wpadly do danego wezla koncowego
         * wyliczyc srednia tych wezlow dla kazdego atrybutu osobno (srodek klastra)
         * stworzyc tablice odleglosci ,kazdy koncowy wezel ma taka tablice 
         * do kazdego klastra (ostatniego wezla) dodawac najblizsze wektory (max 2 * ilosc wektorow w wezle lub odleglosc wieksza od 3 * odleglosc od najdalszego wektora w weźle(do ustalenia) )
         * wyciaganie regol logicznych optymalizacja po najbardziej rygorystycznych kryteriach (przerobic drawNodes)
         * 
         * 
         * mean = Y 
         * !!! w niektorych miejscach nalezy zamienic zbiory weglug mean mniejsze mean na lewo wieksze na praswo i caly zbior przenosimy excel left_is_right ---> zrobione
         * 
         * nie bierzemy odleglosci od najdalszego wektora w klastrze tylko bierzemy srednia odleglosc ze wszystkich --- > zrobione
         * 
         * 
         * poszukaj jakiegos wzoru http://en.wikipedia.org/wiki/Linear_regression tak zeby obliczyc nowy Y(mean) z tych wektorow ktore sa juz w klastrze + te ktore dojda do niego...
         * 
         * 
         * spytaj sie czy maja w klastrach wyswietlane byc tylko wektory bazowe czy razem z tymi ktore zostaly dodane 
         * 
         * pod wektorami dodac opcje klastry 
         * 
         * 
         * !!! jak leci inny watek odpalone sa klastry to niewolno ich wyswietlac bo ich jeszcze nie ma
         * 
         * dodac mozliwosc wyboru pliku, zmienic checkboxy na radiobuttony zablokowac je dopuki sie nie skonczy vectclust
         * 
         * 
         * 
         * !!!! przerobic wczytywanie wektorow na wczytywanie z plikow !!!!
         * 
         * 
         * 
         */

        public DataTable Vectors;        // tabela wektorow                                               
        public DataTable TreeData;       // tabela z danymi

        public Canvas TreeCanvas = new Canvas();
        public double pdistH = 80;       // odleglosc miedzy punktami teoretycznie minimalna (pion)
        int maxNodesQ, levQ;
        public CreatePoint[] p;          // tablica punktow

        //static public string sourceTree = "..//..//..//tree.txt";
        //static public string sourceVectors = "..//..//..//vectors.txt";

        public bool first = true;

        public TreeViewSettings _TVS;
        public DataTable _nodeVectSource;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public DrawTree (TreeViewSettings TVS, DataTable Vect, DataTable TD, DataTable NVS)
        {
            _nodeVectSource = NVS;
            _TVS = TVS;
            Vectors = Vect;
            TreeData = TD;
            TreeCanvas = Tree();
        }

        Canvas Tree()
        {
            Data();
            RadialGradientBrush rgb1 = new RadialGradientBrush(Colors.Cornsilk, Colors.LightSteelBlue);
            rgb1.GradientOrigin = new Point(0.5, 0.05);
            TreeCanvas.Background = rgb1;

            DrawNodes(TreeCanvas.Width, TreeData.Rows[0], TreeCanvas.Width / 2, 1);                       // rysuje drzewo   

            return TreeCanvas;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        void Data()
        {
            TreeCanvas.Children.Clear();

            p = new CreatePoint[TreeData.Rows.Count];

            for (int i = 0; i < TreeData.Rows.Count; i++)
            {
                p[i] = new CreatePoint(this, _nodeVectSource.Rows[i][1].ToString());
            }

            int[] tmp = LoadData.forTreeSize(TreeData);
            levQ = tmp[0];
            maxNodesQ = tmp[1];

            if (levQ > _TVS.TreeViewLevel)
            {
                TreeCanvas.Height = pdistH * _TVS.TreeViewLevel;
                TreeCanvas.Width = TreeCanvas.Height * 1.2;
            }
            else
            {
                TreeCanvas.Height = pdistH * levQ;
                TreeCanvas.Width = TreeCanvas.Height * 1.2;
            }

        }        

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        bool l = false,         // istnieje lewe dziecko 
             r = false;         // istnieje prawe dziecko 

        async public void DrawNodes(double wid, DataRow row, double PX, int H)          // 1- aktualna szer , 2 - dane punktu , 3 - wsp. przodka
        {
            int i = Convert.ToInt32(row[0]) - 1;
            p[i].dr = row;                                          // dane punktu

            double width = wid / 2;
            p[i].X = PX;                                            // wspolrzedna x przodka

            int parent = Convert.ToInt32(row["Parent"]) - 1;        // numer przodka
            DataRow lRule = p[i].LogicRule.NewRow();                // wiersz z regola logiczna

            if (first)
            {
                TreeCanvas.Children.Add(p[i].createPoint(H * (pdistH / 2), p[i].X));
                first = false;
            }
            else if (l == true)
            {
                lRule[0] = p[parent].dr[9];            // zapis regoly log
                lRule[1] = '<';
                lRule[2] = p[parent].dr[10];
                p[i].LogicRule = p[parent].LogicRule.Copy();            // kopiuje regoly logiczne przodka
                p[i].LogicRule.Rows.Add(lRule.ItemArray);               // dodaje kolejna

                TreeCanvas.Children.Add(p[i].createPointL(H * pdistH - (pdistH / 2), p[i].X, width));

                l = false;
            }
            else if (r == true)
            {

                lRule[0] = p[parent].dr[9];            // zapis regoly log
                lRule[1] = '>';
                lRule[2] = p[parent].dr[10];
                p[i].LogicRule = p[parent].LogicRule.Copy();            // kopiuje regoly logiczne przodka
                p[i].LogicRule.Rows.Add(lRule.ItemArray);               // dodaje kolejna

                TreeCanvas.Children.Add(p[i].createPointR(H * pdistH - (pdistH / 2), p[i].X, width));

                r = false;
            }

            l = false;
            r = false;

            if (Convert.ToInt32(row[4]) == 0 && Convert.ToInt32(row[5]) == 0)
            {
                p[i].lastP = true;

                int tmpI = i;
                DataTable tmpVect = Vectors.Copy();
                DataTable tmpLR = p[i].LogicRule.Copy();
                string tmpSource = _nodeVectSource.Rows[i][1].ToString();

                await Task.Run(() => { p[tmpI].cl = new Cluster(tmpVect, tmpLR, tmpSource); });
                //p[i].cl = new Cluster(Vectors, p[i].LogicRule, _nodeVectSource.Rows[i][1].ToString());
            }

            if (Convert.ToInt32(row[4]) != 0)
            {
                if (H % _TVS.TreeViewLevel == 0)
                {
                    ExpandTree ET = new ExpandTree(p[i].Y, p[i].X, row, this);
                    TreeCanvas.Children.Add(ET.exp);
                }
                else
                {
                    l = true;
                    DrawNodes(width, TreeData.Rows[(Convert.ToInt32(row[4])) - 1], p[i].X, H + 1);
                    l = false;
                }
            }

            if (Convert.ToInt32(row[5]) != 0)
            {
                if (H % _TVS.TreeViewLevel == 0)
                {
                    ExpandTree ET = new ExpandTree(p[i].Y, p[i].X, row, this);
                    TreeCanvas.Children.Add(ET.exp);
                }
                else
                {
                    r = true;
                    DrawNodes(width, TreeData.Rows[(Convert.ToInt32(row[5])) - 1], p[i].X, H + 1);
                    r = false;
                }
            }
        }
    }
}
